输入一个网址后,DNS 到底做了什么?

一个被跳过的问题

上一次旅行结束时,数据包已经走完了一段很长的路——离开本地网络、穿过一台又一台路由器、找到服务器上的那个程序、裹上加密的外壳、钻进 Linux 内核,最后拿到了服务器的响应。

但走到最后,它回头看了一眼,发现一件事情不太对劲:

这一路上,它一直在使用一个地址——203.0.113.10

可这个地址是从哪来的,它从没弄明白过。它只记得,自己刚出发的时候手里拿的根本不是这个地址,而是一个名字:

www.example.com

名字变成地址的这一步,被悄悄跳过了。

这次,它决定回过头,把这一步真正走一遍。

名字和地址,是两回事

对人来说,www.example.com 很好记。但网络传输信息的时候,靠的从来不是名字,而是地址——就像寄信要写门牌号,不能只写”张先生家”。

所以在数据包能够出发之前,这台电脑必须先解决一个问题:

这个名字,到底对应着哪一个地址?

负责回答这个问题的,是 DNS

这里要先纠正一个很容易产生的误解:DNS 不是”一台服务器”。它是一整套分布式的名称解析系统,由很多角色分工协作完成——没有哪一台机器单独”知道”全世界所有域名对应的地址。

第一步:先问自己身边的那个人

当浏览器需要知道 www.example.com 对应的地址时,它并不会自己跑去问遍全世界。它会把这个问题,交给一个通常配置在这台电脑或者路由器上的角色——DNS Resolver(也叫递归解析器)。

这个 Resolver 做的第一件事,不是立刻去问别人,而是先看看自己是不是已经知道答案

因为这不是第一次有人问起类似的域名了。之前查过的结果,很可能还被暂时记着——这就是 DNS 缓存。缓存可能存在于浏览器自己、操作系统,也可能存在于 Resolver 这一层,具体分布因环境而异。

如果缓存里已经有答案,故事到这里就结束了:Resolver 直接把结果交回去,不需要再去问任何人。

但假设这是一次全新的查询,缓存里什么都没有——Resolver 就要真正出去打听了。

第二步:一层一层往下问

这里有一个经常被搞混的地方,需要先说清楚:

是 Resolver 代替浏览器,去逐级查询整个 DNS 体系——而不是浏览器自己依次去问根域名、顶级域、权威服务器。

浏览器从头到尾,只和自己的 Resolver 打交道。真正在 DNS 层级里一步步往下问的,是 Resolver。

这个”往下问”的过程,大致是这样的:

flowchart TD
    A[浏览器 / 操作系统] --> B[DNS Resolver]
    B --> C{缓存中有答案吗?}
    C -- 有 --> H[直接返回结果]
    C -- 没有 --> D[询问根域名服务器 Root]
    D --> E[根告知: .com 由谁负责]
    E --> F[询问 .com 顶级域服务器 TLD]
    F --> G[TLD 告知: example.com 的权威服务器是谁]
    G --> I[询问 example.com 的权威 DNS]
    I --> J[得到最终记录]
    J --> H

Root 并不知道 www.example.com 具体对应哪个 IP。它只知道一件事:负责 .com 这个后缀的,是哪一批服务器。

TLD(顶级域)服务器同样不知道最终答案,它只知道:负责 example.com 这个域名的权威服务器是谁。

一直问到 example.com权威 DNS 服务器,才终于问到了真正掌握答案的人——它会给出这个域名对应的具体记录。

Resolver 拿到答案后,一边把结果交给浏览器,一边把这个答案暂时记下来——这样下一次再有人问起同一个域名,就不用重新走一遍这套流程了。

记多久,谁说了算?

这里会自然冒出一个问题:缓存的答案,可以一直用下去吗?

答案是不能。每一条 DNS 记录,都带着一个叫 TTL(Time To Live)的数字,单位是秒。它规定了这条记录最多可以被缓存多久。

时间一到,缓存过期,下一次查询就必须重新走一遍上面那套流程,去问一个新的答案——因为地址背后对应的服务器,随时可能发生变化。

一个名字,可能不止一个答案

到这里,数据包本来以为剩下的事情很简单:拿到一个 IP,结束。

但真实情况要更丰富一些。

首先,一个域名可以同时有多种类型的记录:

1
2
www.example.com → A 记录 → IPv4 地址
www.example.com → AAAA 记录 → IPv6 地址

A 记录对应 IPv4,AAAA 记录对应 IPv6。同一个域名,两种记录可以同时存在。

其次,DNS 给出的答案,也不一定直接就是最终的 IP。有时候,一个域名会先指向另一个域名,这种记录叫 CNAME

数据包这才意识到:DNS 并不是一张写死的”域名对应表”,它背后是一整套灵活的记录系统。

亲眼看一眼这个过程

与其只是听人描述,不如自己去看一眼。在终端里执行:

1
dig www.example.com

结果里最值得关注的是这一段:

1
2
3
4

;; ANSWER SECTION:
www.example.com. 86400 IN A 203.0.113.10

这一行里藏着几件事:记录类型是 A,也就是一个 IPv4 地址;86400 就是这条记录的 TTL,单位是秒;最后的地址,就是这次查询真正要的答案。

如果想分别看 IPv4 和 IPv6:

1
2
dig A www.example.com
dig AAAA www.example.com

如果想亲眼看看前面说的”一层一层往下问”具体是什么样子,可以用:

1
dig +trace www.example.com

需要说明一句:这条命令是 dig 特意模拟出的一次完整逐级查询过程,方便观察和调试用的。真实世界里,浏览器每一次访问网站,并不会真的把根域名、顶级域都问一遍——大量查询都在某一层缓存里就已经结束了,只有缓存都没有命中时,才会真的走到这一整套流程。

数据包终于拿到了真正的答案

查询结束了。

1
2
3
4
5
www.example.com

DNS 解析

203.0.113.10

这一次,数据包终于弄明白了自己一直在使用的这个地址,究竟是怎么来的——不是凭空出现的,而是浏览器把问题交给 Resolver,Resolver 或是从缓存里直接给出答案,或是沿着根、顶级域、权威服务器这条链路一层层问出来的。

它低头看了看手里这个地址,长长地舒了一口气。

这一次,终点确实是清楚的了。

但一个熟悉的问题,很快又冒了出来。

它记得,自己曾经因为”只知道 IP 还不够”而卡住过一次——那是因为,知道最终要去哪里,和知道眼前这一步该交给谁,从来都不是同一件事。

现在,它手里的这个 IP 是真实查出来的,不再是一个被直接告知的结果。

可那个问题,会不会又要重新问一遍?

这一跳,我到底应该交给谁?

这一次,它想真正弄清楚这背后发生了什么。

输入一个网址后,DNS 到底做了什么?

https://pengtech.net/network/packet-journey/dns-resolution copy.html

作者

鹏叔

发布于

2026-09-23

更新于

2026-09-23

许可协议

评论